package com.kcht.itsed.mws.aleframework.biz;

import com.kcht.itsed.mws.aleframework.intf.ILogicalReaderContainer;
import com.kcht.itsed.mws.aleframework.intf.IReaderCommandFactory;
import com.kcht.itsed.mws.aleframework.intf.ISubscriptionSender;
import com.kcht.itsed.mws.aleframework.intf.ITagMemoryContainer;
import com.kcht.itsed.mws.alemodel.CCSpec;
import com.kcht.itsed.mws.alemodel.Document;
import com.kcht.itsed.mws.alemodel.ECSpec;
import com.kcht.itsed.mws.alemodel.LRSpec;
import com.kcht.itsed.mws.commmodel.CRAP;
import com.shhic.itsed.mws.deviceintf.AntennaProtocol;
import com.shhic.itsed.mws.deviceintf.ReaderCommand;
import com.kcht.itsed.mws.extendalemodel.PRSpec;
import com.kcht.itsed.mws.persist.dao.IPhysicalReaderDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 阅读器命令工厂生成器
 * @author 张文硕
 *
 */
@Component
public class ReaderCommandFactoryGenerator{
	
	
	public static abstract class AbstractReaderCommandFactory<T extends Document> {
		protected ILogicalReaderContainer lrContainer;
		protected ITagMemoryContainer tmContainer;
		protected ISubscriptionSender subscriptionSender;
		protected IPhysicalReaderDao prDao;
		protected T spec;
		
		public AbstractReaderCommandFactory(T spec) {
			this.spec = spec;
		}

		/**
		 * 根据阅读器生成命令原型
		 * 每个阅读器一个
		 * @return
		 */
		protected List<ReaderCommand> generateReaderCommandPrototypeOfReaders(){
			List<String> lrList;
			if(spec instanceof ECSpec)lrList = ((ECSpec)spec).getLogicalReaders().getLogicalReader();
			else if(spec instanceof CCSpec)lrList = ((CCSpec)spec).getLogicalReaders().getLogicalReader();
			else throw new RuntimeException("出现了非EC/CC规则，是不行的");
			List<ReaderCommand> rcl = new LinkedList<>();
			lrList.forEach(lrName->{	//目前没有考虑复合阅读器
				LRSpec lr = lrContainer.getLRSpec(lrName);
				lr.getProperties().getProperty().forEach(p->{
					if(p.getName().equals("crap"))	//CRAP元组
						rcl.add(generateReaderCommandFromCRAP(p.getValue()));
					else if(p.getName().equals("prName"))	//整个物理阅读器
						rcl.add(generateReaderCommandFromPR(p.getValue()));
				});
			});
			return rcl;
		}
		
		//从CRAP元组描述值生成一个ReaderCommand
		private ReaderCommand generateReaderCommandFromCRAP(String crapValue) {
			CRAP crap = new CRAP(crapValue);
			ReaderCommand rc = new ReaderCommand();
			rc.setAntennaProtocolSet(new HashSet<AntennaProtocol>());
			rc.getAntennaProtocolSet().add(new AntennaProtocol(crap.getAntenna(),crap.getProtocol()));
			rc.setReaderClass(crap.getDeviceClass());
			rc.setReaderId(crap.getReaderId());
			rc.setReaderIp(crap.getReaderIp());
			rc.setReaderPort(crap.getReaderPort());
			return rc;
		}
		
		//从物理阅读器生成一个ReaderCommand
		private ReaderCommand generateReaderCommandFromPR(String prName) {
			ReaderCommand rc = new ReaderCommand();
			rc.setAntennaProtocolSet(new HashSet<AntennaProtocol>());
			prDao.findByName(prName).ifPresent(pr->{
				PRSpec prSpec = pr.getPrSpec();
				prSpec.getAntennaList().getAntenna().forEach(ant->{
					Set<String> protocols = ant.getProtocol().stream().collect(Collectors.toSet());
					rc.getAntennaProtocolSet().add(new AntennaProtocol(ant.getAntennaNo(),protocols));
				});
				rc.setReaderClass(prSpec.getReaderClass());
				rc.setReaderId(prSpec.getReaderId());
				rc.setReaderIp(prSpec.getReaderIp());
				rc.setReaderPort(prSpec.getReaderPort());
			});
			return rc;
		}
	}
	
	@Autowired
	ITagMemoryContainer tagMemoryContainer;
	@Autowired ILogicalReaderContainer logicalReaderContainer;
	@Autowired IPhysicalReaderDao prDao;

	@SuppressWarnings("unchecked")
	public <T extends Document> IReaderCommandFactory generateFullyReaderCommands(T spec){
		AbstractReaderCommandFactory<T> rcf;
		if(spec instanceof ECSpec)rcf = (AbstractReaderCommandFactory<T>) new EcReaderCommandFactory((ECSpec)spec);
		else if(spec instanceof CCSpec)rcf = (AbstractReaderCommandFactory<T>) new CcReaderCommandFactory((CCSpec)spec);
		else throw new RuntimeException("这个接口只能填入ECSpec或CCSpec");
		rcf.lrContainer = logicalReaderContainer;
		rcf.tmContainer = tagMemoryContainer;
		rcf.prDao = prDao;
		return (IReaderCommandFactory) rcf;
	}
}
